package com.example.controller.admin;



import com.example.dto.AiResult;
import com.example.dto.ContentDto;
import com.example.utils.JsonUtils;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.AsyncContext;
import jakarta.servlet.http.HttpServletResponse;
import okhttp3.*;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import jakarta.servlet.http.HttpServletRequest;

@RestController
public class SeekController {
    private static final Logger logger = LoggerFactory.getLogger(SeekController.class);
    private static final String DONE = "[DONE]";
    private static final Integer TIMEOUT = 120;
    private static final String AI_URL = "https://api.deepseek.com/chat/completions";

    @Value("${api.password:}")
    private String apiPassword;

    // 添加构造函数，在Bean初始化后打印API密钥状态
    public SeekController() {
        // 构造函数
    }

    @PostConstruct
    public void init() {
        logger.info("SeekController initialized. API密钥状态: {}", 
            apiPassword != null && !apiPassword.isEmpty() ? 
            "已加载 (前6位: " + (apiPassword.length() > 6 ? apiPassword.substring(0, 6) : apiPassword) + "...)" : 
            "未加载");
        
        // 如果密钥为空，尝试使用硬编码密钥（不推荐但可用于测试）
        if (apiPassword == null || apiPassword.isEmpty()) {
            logger.warn("API密钥未从配置加载，将使用硬编码密钥（仅用于测试）");
            apiPassword = "sk-df9036032b8e46edb075bc8058460a76";
        }
    }

    @GetMapping("/health")
    public ResponseEntity<Map<String, String>> healthCheck() {
        Map<String, String> status = new HashMap<>();
        status.put("status", "UP");
        status.put("message", "Server is running");
        status.put("apiKeyStatus", apiPassword != null && !apiPassword.isEmpty() ? 
            "Loaded (starts with: " + (apiPassword.length() > 6 ? apiPassword.substring(0, 6) : apiPassword) + "...)" : 
            "Not loaded");
        return ResponseEntity.ok(status);
    }

    @GetMapping(value = "/stream")
    public void handleSse(String message, HttpServletRequest request, HttpServletResponse response) {
        try {
            // Log incoming request
            logger.info("Received request with message: {}", message);
            
            response.setContentType("text/event-stream");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("X-Accel-Buffering", "no"); // Prevent proxy buffering
            response.setHeader("Connection", "keep-alive");

            // For test/ping messages, return a simple response instead of calling the AI API
            if (message == null || message.trim().isEmpty() || "ping".equalsIgnoreCase(message.trim())) {
                try (PrintWriter pw = response.getWriter()) {
                    sendDataChunk(pw, "Server is alive and responding. This is a test message.");
                    sendEndMarker(pw);
                }
                return;
            }

            // Create an async context with a long timeout
            final AsyncContext asyncContext = request.startAsync(request, response);
            asyncContext.setTimeout(300000); // 5 minutes timeout
            
            // Get writer from async context
            final PrintWriter asyncWriter = asyncContext.getResponse().getWriter();
            
            // Pass the async context to the async method
            getAiResultAsync(asyncContext, asyncWriter, message);
        } catch (IOException e) {
            logger.error("SSE处理失败", e);
            throw new RuntimeException("服务端流处理异常", e);
        }
    }

    private void getAiResultAsync(AsyncContext asyncContext, PrintWriter pw, String content) {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(TIMEOUT, TimeUnit.SECONDS)
                .build();

        try {
            Request request = buildRequest(content);
    
            EventSource.Factory factory = EventSources.createFactory(client);
            factory.newEventSource(request, new EventSourceListener() {
                @Override
                public void onOpen(EventSource eventSource, Response response) {
                    logger.info("SSE连接已建立");
                }
    
                @Override
                public void onEvent(EventSource eventSource, String id, String type, String data) {
                    if (DONE.equals(data)) {
                        // Send end marker when done
                        sendEndMarker(pw);
                        asyncContext.complete();
                        return;
                    }
    
                    try {
                        String chunk = processDataChunk(data);
                        sendDataChunk(pw, chunk);
                    } catch (Exception e) {
                        logger.error("数据处理异常", e);
                        eventSource.cancel();
                        sendEndMarker(pw);
                        asyncContext.complete();
                    }
                }
    
                @Override
                public void onClosed(EventSource eventSource) {
                    logger.info("SSE连接已关闭");
                    sendEndMarker(pw);
                    asyncContext.complete();
                }
    
                @Override
                public void onFailure(EventSource eventSource, Throwable t, Response response) {
                    String errorMessage = t != null ? t.getMessage() : "Unknown error";
                    logger.error("SSE通信失败: {}", errorMessage);
                    if (response != null) {
                        try {
                            ResponseBody responseBody = response.body();
                            String responseBodyString = responseBody != null ? responseBody.string() : "空响应体";
                            logger.error("响应状态码: {}, 响应体: {}", response.code(), responseBodyString);
                            
                            // 发送更详细的错误信息给客户端
                            String clientErrorMsg = "Error connecting to DeepSeek API: " + 
                                                    "Status Code: " + response.code() + 
                                                    ", Message: " + responseBodyString;
                            sendDataChunk(pw, clientErrorMsg);
                        } catch (Exception e) {
                            logger.error("读取响应体失败", e);
                        }
                    } else {
                        sendDataChunk(pw, "Error connecting to DeepSeek API: " + errorMessage);
                    }
                    
                    sendEndMarker(pw);
                    asyncContext.complete();
                }
            });
        } catch (Exception e) {
            logger.error("Error creating EventSource", e);
            sendDataChunk(pw, "Server error: " + e.getMessage());
            sendEndMarker(pw);
            asyncContext.complete();
        }
    }

    private Request buildRequest(String content) {
        Map<String, Object> params = new HashMap<>();
        params.put("model", "deepseek-chat");
        params.put("stream", true);
        params.put("temperature", 0.7);
        params.put("max_tokens", 4000);

        Map<String, String> messageMap = new HashMap<>();
        messageMap.put("role", "user");
        messageMap.put("content", content);

        // 添加系统消息，指导AI使用Markdown格式
        Map<String, String> systemMessage = new HashMap<>();
        systemMessage.put("role", "system");
        systemMessage.put("content", "你是一个专业的AI助手。请在回答中适当使用Markdown格式，包括代码块```、内联代码`、**加粗**、*斜体*和[链接](URL)等。对于代码示例，请使用正确的语法高亮。每个自然段落的开头请添加两个全角空格（　　）缩进，以提高可读性。列表、代码块、标题等特殊格式不需要缩进。");

        List<Map<String, String>> messages = new ArrayList<>();
        messages.add(systemMessage);  // 先添加系统消息
        messages.add(messageMap);     // 再添加用户消息
        params.put("messages", messages);

        RequestBody body = RequestBody.create(
                JsonUtils.convertObj2Json(params),
                MediaType.get("application/json; charset=utf-8")
        );

        // 打印请求信息用于调试
        logger.info("API请求URL: {}", AI_URL);
        logger.info("API密钥前6位: {}", apiPassword.length() > 6 ? apiPassword.substring(0, 6) + "..." : apiPassword);
        logger.info("请求体: {}", JsonUtils.convertObj2Json(params));
        
        // 确保API密钥格式正确，以sk-开头
        String authHeader = "Bearer " + apiPassword;
        logger.info("Authorization头: {}", authHeader.substring(0, 12) + "...");

        return new Request.Builder()
                .url(AI_URL)
                .addHeader("Authorization", authHeader)
                .addHeader("Accept", "text/event-stream")
                .post(body)
                .build();
    }

    private String processDataChunk(String data) {
        AiResult aiResult = JsonUtils.convertJson2Obj(data, AiResult.class);

        // 添加空安全保护
        if (aiResult == null ||
                aiResult.getChoices() == null ||
                aiResult.getChoices().isEmpty()) {
            return "";
        }

        return aiResult.getChoices().get(0)  // changed getFirst() -> get(0)
                .getDelta()
                .getContent();
    }


    private void sendDataChunk(PrintWriter pw, String content) {
        if (content == null || content.isEmpty()) return;

        try {
            String jsonPayload = JsonUtils.convertObj2Json(new ContentDto(content));
            pw.write("data: " + jsonPayload + "\n\n");
            pw.flush();
        } catch (Exception e) {
            logger.error("数据发送失败", e);
            throw new RuntimeException("流数据发送异常", e);
        }
    }

    private void sendEndMarker(PrintWriter pw) {
        try {
            pw.write("data: end\n\n");
            pw.flush();
        } catch (Exception e) {
            logger.error("结束标记发送失败", e);
        }
    }
}
